package com.pubinfo.passbook.data.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.pubinfo.passbook.common.config.ApplicationConfig;
import com.pubinfo.passbook.common.entity.*;
import com.pubinfo.passbook.common.exception.ServiceException;
import com.pubinfo.passbook.common.mapper.TFileOpenElectronicFtpMapper;
import com.pubinfo.passbook.common.mapper.TFileOpenEnclosureFtpMapper;
import com.pubinfo.passbook.common.mapper.TFileOpenFtpMapper;
import com.pubinfo.passbook.common.mapper.TMdmAccountingTitleMapper;
import com.pubinfo.passbook.common.model.dto.open.*;
import com.pubinfo.passbook.common.model.http.baseEntity.BaseBody;
import com.pubinfo.passbook.common.model.http.baseEntity.Baseinfo;
import com.pubinfo.passbook.common.model.http.baseEntity.Message;
import com.pubinfo.passbook.common.model.http.baseEntity.request.IRequest;
import com.pubinfo.passbook.common.model.http.baseEntity.request.MessageList;
import com.pubinfo.passbook.common.model.http.baseEntity.request.RequestEnvelope;
import com.pubinfo.passbook.common.model.http.request.AutoCreateWriteoff.AutoCreateWriteoffBody;
import com.pubinfo.passbook.common.model.http.request.AutoCreateWriteoff.AutoCreateWriteoffMessageList;
import com.pubinfo.passbook.common.model.http.request.GainWriteoffInstStatus.GainWriteoffInstStatusBody;
import com.pubinfo.passbook.common.model.http.request.GainWriteoffInstStatus.GainWriteoffInstStatusItems;
import com.pubinfo.passbook.common.model.http.response.GetAutoCreateWriteoff.WriteoffEnvelope;
import com.pubinfo.passbook.common.model.http.response.GetAutoCreateWriteoff.WriteoffMessage;
import com.pubinfo.passbook.common.model.http.response.GetWriteoffInstStatus.WriteoffInstStatusEnvelope;
import com.pubinfo.passbook.common.model.http.response.GetWriteoffInstStatus.WriteoffInstStatusMessage;
import com.pubinfo.passbook.common.model.ruler.UserAcc;
import com.pubinfo.passbook.common.service.master.*;
import com.pubinfo.passbook.common.service.ruler.CheckService;
import com.pubinfo.passbook.common.service.ruler.InformationService;
import com.pubinfo.passbook.data.service.MssService;
import com.pubinfo.passbook.data.service.OpenWiteoffService;
import com.pubinfo.passbook.data.service.TFileInfoService;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Service
@Slf4j
public class OpenWiteoffServiceImpl implements OpenWiteoffService {
  
  @Autowired
  TWiteoffShareAttachmentService shareAttachmentService;
  @Autowired
  TRuleUserWiteoffService witeoffService;
  @Autowired
  MssService mssService;
  @Resource
  ApplicationConfig config;
  @Autowired
  CheckService checkService;
  @Autowired
  TWiteoffInstanceService instanceService;
  @Autowired
  TWiteoffAttchmentService attchmentService;
  @Autowired
  TWiteoffInvoiceInfoService invoiceInfoService;
  @Autowired
  TWiteoffOpenPickingService openPickingService;
  @Autowired
  TWiteoffInstanceSubitemService subitemService;
  @Autowired
  TWiteoffPayMentService payMentService;
  @Autowired
  TWiteoffRelateSupplierService relateSupplierService;
  @Autowired
  InformationService informationService;
  @Autowired
  ITFileEnclosureFtpService itFileEnclosureFtpService;
  @Autowired
  TFileOpenFtpMapper openFtpMapper;
  @Autowired
  TFileOpenElectronicFtpMapper openElectronicFtpMapper;
  @Autowired
  TFileOpenEnclosureFtpMapper openEnclosureFtpMapper;
  @Autowired
  TFileInfoService tFileInfoService;
  @Autowired
  TMdmAccountingTitleMapper tMdmAccountingTitleMapper;
  
  @Override
  public WriteoffMessage createWriteoff(WiteoffData data) {
    UserAcc userAcc = checkService.getUserAcc(data.getAccount(), true);
    data.setUserAcc(userAcc);
    List<WiteoffSubitemData> subitemData = data.getLineItems();
    if (CollectionUtils.isEmpty(subitemData)) {
      throw new ServiceException("子项不能为空");
    }
  
    Integer pickingMode = data.getPickingMode();
    //accountName  accountCode   sapCostCenterCode   debitAccountName
    //设置一单清专用的金额
    if(pickingMode==5 || pickingMode==7)
    {
      data.setAccountType("2");
      //发票挂账&往来转销设置默认值
      data.setAccountCode("G000343924");
      data.setAccountName("浙江省公路管理局");
    }
    else if(pickingMode==8)
    {
      TMdmAccountingTitle tMdmAccountingTitle=tMdmAccountingTitleMapper.selectTMdmAccountingTitleByBankn(data.getDelegationBankCode());
      data.setDelegationBankCode(null);
      data.setAccountType("1");
      if(tMdmAccountingTitle!=null)
      {
        data.setAccountCode(tMdmAccountingTitle.getSaknr());
        data.setAccountName(tMdmAccountingTitle.getTxt50());
      }
      else
      {
        throw new ServiceException("扣划账号错误");
      }
    }

    subitemData.stream().forEach(witeoffSubitemData -> {
//      witeoffSubitemData.setSum(witeoffSubitemData.getPriceSum().add(new BigDecimal(witeoffSubitemData.getInputTaxSum())));

      //设置子项
      //8:预付款  //银行扣款挂账
      //7挂账不付款 //发票挂账
      //5:往来转销
      if (pickingMode == 8) {
        //银行扣款挂账&往来转销=G000343924
        witeoffSubitemData.setBudgetType(2);
        witeoffSubitemData.setBudgetItemCode("CW1121");
        //车辆使用及租赁费
        witeoffSubitemData.setBudgetItemName("车辆使用及租赁费");
        witeoffSubitemData.setDebitAccountCode("G000343924");
        witeoffSubitemData.setDebitAccountType(2);
        //设置父项
        //   data.setAccountCode(2);
        //data.setAccountName(2);
        data.setAccountType("1");
      } else if (pickingMode == 7) {
        witeoffSubitemData.setBudgetItemCode("CW1121");
        witeoffSubitemData.setBudgetItemName("车辆使用及租赁费");
        witeoffSubitemData.setBudgetType(1);
        witeoffSubitemData.setDebitAccountCode("6400162005");
        witeoffSubitemData.setDebitAccountType(1);
        data.setAccountCode("G000343924");
        data.setAccountName("浙江省公路管理局");
        data.setAccountType("2");
      } else if (pickingMode == 5) {
        witeoffSubitemData.setBudgetType(2);
        witeoffSubitemData.setBudgetItemCode("CW1121");
        witeoffSubitemData.setBudgetItemName("车辆使用及租赁费");
        witeoffSubitemData.setDebitAccountCode("G000343924");
        witeoffSubitemData.setDebitAccountType(2);
        data.setAccountCode("G000343924");
        data.setAccountName("浙江省公路管理局");
        data.setAccountType("2");
      } else {
        //如果找到了其他类型，则报错
        throw new ServiceException("ETC报账不支持该类型pickingMode:" + pickingMode);
      }
    });
    //上传文件
    List<WiteoffAttchment> witeoffAttchmentList = tFileInfoService.uploadOpenFile(data.getAttchmentAdds());
    data.setAttchmentAdds(witeoffAttchmentList);
    return postXmlAndSave(data);
  }
  
  @SneakyThrows
  @Override
  public WriteoffInstStatusMessage getWriteoffInstStatus(GainWriteoffInstStatusItems statusItems, String systemCode) {
    List<GainWriteoffInstStatusItems> instStatusItems = new ArrayList<>();
    instStatusItems.add(statusItems);
    System.out.println(config);
    String postUrl = config.getEsb().getUrl() + config.getEsb().getApi().getGainWriteoffInstStatus();
    BaseBody baseBody = new BaseBody();
    Message message = new Message(new MessageList(instStatusItems));
    baseBody.setBaseinfo(Baseinfo.createBaseinfo("gainWriteoffInstStatus", systemCode, new Date()));
    baseBody.setMessage(message);
    RequestEnvelope requestEnvelope = new RequestEnvelope();
    GainWriteoffInstStatusBody body = new GainWriteoffInstStatusBody();
    IRequest IRequest = new IRequest();
    IRequest.setBaseBody(baseBody);
    body.setIRequest(IRequest);
    requestEnvelope.setRequestBody(body);
    //发送post请求
    String s = mssService.sendPost(new XmlMapper().writeValueAsString(requestEnvelope), postUrl);
    //处理&#60;和&#62;的乱码
    s = s.replaceAll("&#60;", "<").replaceAll("&#62;", ">");
    System.out.println(s);
    WriteoffInstStatusEnvelope writeoffInstStatusEnvelope = new XmlMapper().readValue(s, WriteoffInstStatusEnvelope.class);
    WriteoffInstStatusMessage writeoffInstStatusBodyMessage = new XmlMapper().readValue(writeoffInstStatusEnvelope.getBody().getEResponse().getBaseBody().getMessage().getMessage(), WriteoffInstStatusMessage.class);
    return writeoffInstStatusBodyMessage;
  }
  
  private void setJobOrRetireDTOId(WiteoffData base) {
    for(int i=0;i<base.getLineItems().size();i++)
    {
      String itemUUID = UUID.randomUUID().toString();
      base.getLineItems().get(i).setOtherSystemDetailId(itemUUID);
      if(base.getOpenItemPickings().size()>i)
      {
        base.getOpenItemPickings().get(i).setOtherSystemDetailId(itemUUID);
      }
    }
    base.setOtherSystemMainId(UUID.randomUUID().toString());
  }
  
  @SneakyThrows
  private WriteoffMessage postXmlAndSave(WiteoffData witeoffBase) {
    JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(witeoffBase));
    setJobOrRetireDTOId(witeoffBase);
    BaseBody baseBody = new BaseBody();
    Message message = new Message(new AutoCreateWriteoffMessageList(witeoffBase));
    baseBody.setBaseinfo(Baseinfo.createBaseinfo("AutoCreateWriteoff", witeoffBase.getSystemCode(), new Date()));
    baseBody.setMessage(message);
    RequestEnvelope requestEnvelope = new RequestEnvelope();
    AutoCreateWriteoffBody body = new AutoCreateWriteoffBody();
    IRequest IRequest = new IRequest();
    IRequest.setBaseBody(baseBody);
    body.setIRequest(IRequest);
    requestEnvelope.setRequestBody(body);
  
    saveInstance(witeoffBase, new XmlMapper().writeValueAsString(requestEnvelope), jsonObject);
  
    //发送post请求
    String s = null;
    WriteoffEnvelope writeoffEnvelope = null;
    log.info(new XmlMapper().writeValueAsString(requestEnvelope));
  
    String postUrl = config.getEsb().getUrl() + config.getEsb().getApi().getAutoCreateWriteoff();
    s = mssService.sendPost(new XmlMapper().writeValueAsString(requestEnvelope), postUrl);
    writeoffEnvelope = new XmlMapper().readValue(s, WriteoffEnvelope.class);
    s = s.replaceAll("&#60;", "<").replaceAll("&#62;", ">");
    log.info(writeoffEnvelope.getBody().getEResponse().getBaseBody().getMessage().getMessage());
    
    WriteoffMessage writeoffMessage = null;
    String thisMessage = writeoffEnvelope.getBody().getEResponse().getBaseBody().getMessage().getMessage().replaceAll("<!\\[CDATA\\[", "").replaceAll("\\]\\]>", "");
    writeoffMessage = new XmlMapper().readValue(thisMessage, WriteoffMessage.class);
    log.info(JSONObject.toJSONString(writeoffMessage));
    
    return writeoffMessage;
  }
  
  @Transactional
  public void saveInstance(WiteoffData witeoffData, String xml, JSONObject json) {
    TWiteoffInstance instance = new TWiteoffInstance(witeoffData, xml, json);
    instanceService.save(instance);
  
    //将attchments添加入数据库
    List<WiteoffAttchment> attchments = witeoffData.getAttchmentAdds();
    List<TWiteoffAttchment> attchmentList = new ArrayList<>();
    if (!CollectionUtils.isEmpty(attchments)) {
      attchments.stream().forEach(tWiteoffAttchment -> {
        TWiteoffAttchment attchment = new TWiteoffAttchment(tWiteoffAttchment);
        attchment.setOtherSystemMainId(witeoffData.getOtherSystemMainId());
        attchmentList.add(attchment);
      });
      List<String> attchmentIds = attchments.stream().map(WiteoffAttchment::getId).collect(Collectors.toList());
      openElectronicFtpMapper.updateFileOpenFtpByIds(instance.getOtherSystemMainId(), attchmentIds);
      openEnclosureFtpMapper.updateFileOpenFtpByIds(instance.getOtherSystemMainId(), attchmentIds);
    }
    attchmentService.saveBatch(attchmentList);
//    保存报账子单
    if(CollectionUtils.isNotEmpty(TWiteoffInstanceSubitem.toList(witeoffData.getLineItems(), witeoffData.getOtherSystemMainId())))
    {
      subitemService.saveBatch(TWiteoffInstanceSubitem.toList(witeoffData.getLineItems(), witeoffData.getOtherSystemMainId()));
    }
    //将openPickings添加入数据库
    List<WiteoffOpenPicking> openPickings = witeoffData.getOpenItemPickings();
  
    openPickingService.saveBatch(TWiteoffOpenPicking.toList(openPickings, witeoffData.getOtherSystemMainId()));
  
    //   payMentService.saveBatch(payMents);
    //将relateSuppliers添加入数据库
    List<WiteoffRelateSupplier> relateSuppliers = witeoffData.getRelateSuppliers();
  
    relateSupplierService.saveBatch(TWiteoffRelateSupplier.toList(relateSuppliers, witeoffData.getOtherSystemMainId()));
    //将shareAttachments添加入数据库
  
  }
}
